Upgrade async_task to 4.3.0 This project was upgraded with external_updater. Usage: tools/external_updater/updater.sh update rust/crates/async-task For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md Test: TreeHugger Change-Id: I45dca5604ff41679993b26a30a1dbfb40fe680f1 
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index d3b06d7..e80a435 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json 
@@ -1,6 +1,6 @@  {  "git": { - "sha1": "de0c79d171e95d1cbbd4becf678cc43ea689551e" + "sha1": "f910d25edb04d05a24c9e58d73a4e5d8a31163a6"  },  "path_in_vcs": ""  } \ No newline at end of file 
diff --git a/Android.bp b/Android.bp index 8c176c1..a46517c 100644 --- a/Android.bp +++ b/Android.bp 
@@ -42,7 +42,7 @@  host_supported: true,  crate_name: "async_task",  cargo_env_compat: true, - cargo_pkg_version: "4.2.0", + cargo_pkg_version: "4.3.0",  srcs: ["src/lib.rs"],  edition: "2018",  features: [ 
diff --git a/CHANGELOG.md b/CHANGELOG.md index fe87187..d0a3e0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md 
@@ -1,3 +1,9 @@ +# Version 4.3.0 + +- Bump MSRV to Rust 1.47. (#30) +- Evaluate the layouts for the tasks at compile time. (#30) +- Add layout_info field to TaskVTable so that debuggers can decode raw tasks. (#29) +  # Version 4.2.0    - Add `Task::is_finished`. (#19) 
diff --git a/Cargo.lock.saved b/Cargo.lock.saved new file mode 100644 index 0000000..388f5ba --- /dev/null +++ b/Cargo.lock.saved 
@@ -0,0 +1,443 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "async-channel" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +dependencies = [ + "async-task 4.2.0", + "concurrent-queue", + "fastrand", + "futures-lite", + "once_cell", + "slab", +] + +[[package]] +name = "async-fs" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b3ca4f8ff117c37c278a2f7415ce9be55560b846b5bc4412aaa5d29c1c3dae2" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07" +dependencies = [ + "concurrent-queue", + "futures-lite", + "libc", + "log", + "once_cell", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "winapi", +] + +[[package]] +name = "async-lock" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-net" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5373304df79b9b4395068fb080369ec7178608827306ce4d081cba51cac551df" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2c06e30a24e8c78a3987d07f0930edf76ef35e027e7bdb063fccafdad1f60c" +dependencies = [ + "async-io", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "libc", + "once_cell", + "signal-hook", + "winapi", +] + +[[package]] +name = "async-task" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" + +[[package]] +name = "async-task" +version = "4.3.0" +dependencies = [ + "atomic-waker", + "easy-parallel", + "flaky_test", + "flume", + "once_cell", + "smol", +] + +[[package]] +name = "atomic-waker" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "blocking" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" +dependencies = [ + "async-channel", + "async-task 4.2.0", + "atomic-waker", + "fastrand", + "futures-lite", + "once_cell", +] + +[[package]] +name = "cache-padded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "concurrent-queue" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +dependencies = [ + "cache-padded", +] + +[[package]] +name = "easy-parallel" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946" + +[[package]] +name = "event-listener" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "flaky_test" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479cde5eb168cf5a056dd98f311cbfab7494c216394e4fb9eba0336827a8db93" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "flume" +version = "0.10.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ceeb589a3157cac0ab8cc585feb749bd2cea5cb55a6ee802ad72d9fd38303da" +dependencies = [ + "spin", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "libc" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" + +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "once_cell" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" + +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "polling" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +dependencies = [ + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "winapi", +] + +[[package]] +name = "proc-macro2" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "signal-hook" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" + +[[package]] +name = "smol" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cf3b5351f3e783c1d79ab5fc604eeed8b8ae9abd36b166e8b87a089efd85e4" +dependencies = [ + "async-channel", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" +dependencies = [ + "lock_api", +] + +[[package]] +name = "syn" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 
diff --git a/Cargo.toml b/Cargo.toml index 7847dd8..6e989e5 100644 --- a/Cargo.toml +++ b/Cargo.toml 
@@ -11,12 +11,13 @@    [package]  edition = "2018" -rust-version = "1.39" +rust-version = "1.47"  name = "async-task" -version = "4.2.0" +version = "4.3.0"  authors = ["Stjepan Glavina <stjepang@gmail.com>"]  exclude = ["/.*"]  description = "Task abstraction for building executors" +readme = "README.md"  keywords = [  "futures",  "task", 
diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 7dc7c73..8c611bf 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig 
@@ -3,10 +3,10 @@  # When publishing a new version:  # - Update CHANGELOG.md  # - Create "v4.x.y" git tag -version = "4.2.0" +version = "4.3.0"  authors = ["Stjepan Glavina <stjepang@gmail.com>"]  edition = "2018" -rust-version = "1.39" +rust-version = "1.47"  license = "Apache-2.0 OR MIT"  repository = "https://github.com/smol-rs/async-task"  description = "Task abstraction for building executors" 
diff --git a/METADATA b/METADATA index 9a5cdf5..799c6da 100644 --- a/METADATA +++ b/METADATA 
@@ -1,3 +1,7 @@ +# This project was upgraded with external_updater. +# Usage: tools/external_updater/updater.sh update rust/crates/async-task +# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md +  name: "async_task"  description: "Task abstraction for building executors"  third_party { @@ -7,13 +11,13 @@  }  url {  type: ARCHIVE - value: "https://static.crates.io/crates/async_task/async_task-4.2.0.crate" + value: "https://static.crates.io/crates/async_task/async_task-4.3.0.crate"  } - version: "4.2.0" + version: "4.3.0"  license_type: NOTICE  last_upgrade_date {  year: 2022 - month: 6 - day: 22 + month: 12 + day: 6  }  } 
diff --git a/src/lib.rs b/src/lib.rs index 4a868bf..dd689ec 100644 --- a/src/lib.rs +++ b/src/lib.rs 
@@ -74,6 +74,17 @@    extern crate alloc;   +/// We can't use `?` in const contexts yet, so this macro acts +/// as a workaround. +macro_rules! leap { + ($x: expr) => {{ + match ($x) { + Some(val) => val, + None => return None, + } + }}; +} +  mod header;  mod raw;  mod runnable; 
diff --git a/src/raw.rs b/src/raw.rs index 9b5854c..bb031da 100644 --- a/src/raw.rs +++ b/src/raw.rs 
@@ -1,4 +1,4 @@ -use alloc::alloc::Layout; +use alloc::alloc::Layout as StdLayout;  use core::cell::UnsafeCell;  use core::future::Future;  use core::mem::{self, ManuallyDrop}; @@ -9,7 +9,7 @@    use crate::header::Header;  use crate::state::*; -use crate::utils::{abort, abort_on_panic, extend}; +use crate::utils::{abort, abort_on_panic, max, Layout};  use crate::Runnable;    /// The vtable for a task. @@ -34,6 +34,12 @@    /// Creates a new waker associated with the task.  pub(crate) clone_waker: unsafe fn(ptr: *const ()) -> RawWaker, + + /// The memory layout of the task. This information enables + /// debuggers to decode raw task memory blobs. Do not remove + /// the field, even if it appears to be unused. + #[allow(unused)] + pub(crate) layout_info: &'static Option<TaskLayout>,  }    /// Memory layout of a task. @@ -45,7 +51,7 @@  #[derive(Clone, Copy)]  pub(crate) struct TaskLayout {  /// Memory layout of the whole task. - pub(crate) layout: Layout, + pub(crate) layout: StdLayout,    /// Offset into the task at which the schedule function is stored.  pub(crate) offset_s: usize, @@ -80,6 +86,39 @@  }  }   +impl<F, T, S> RawTask<F, T, S> { + const TASK_LAYOUT: Option<TaskLayout> = Self::eval_task_layout(); + + /// Computes the memory layout for a task. + #[inline] + const fn eval_task_layout() -> Option<TaskLayout> { + // Compute the layouts for `Header`, `S`, `F`, and `T`. + let layout_header = Layout::new::<Header>(); + let layout_s = Layout::new::<S>(); + let layout_f = Layout::new::<F>(); + let layout_r = Layout::new::<T>(); + + // Compute the layout for `union { F, T }`. + let size_union = max(layout_f.size(), layout_r.size()); + let align_union = max(layout_f.align(), layout_r.align()); + let layout_union = Layout::from_size_align(size_union, align_union); + + // Compute the layout for `Header` followed `S` and `union { F, T }`. + let layout = layout_header; + let (layout, offset_s) = leap!(layout.extend(layout_s)); + let (layout, offset_union) = leap!(layout.extend(layout_union)); + let offset_f = offset_union; + let offset_r = offset_union; + + Some(TaskLayout { + layout: unsafe { layout.into_std() }, + offset_s, + offset_f, + offset_r, + }) + } +} +  impl<F, T, S> RawTask<F, T, S>  where  F: Future<Output = T>, @@ -97,7 +136,9 @@  /// It is assumed that initially only the `Runnable` and the `Task` exist.  pub(crate) fn allocate(future: F, schedule: S) -> NonNull<()> {  // Compute the layout of the task for allocation. Abort if the computation fails. - let task_layout = abort_on_panic(|| Self::task_layout()); + // + // n.b. notgull: task_layout now automatically aborts instead of panicking + let task_layout = Self::task_layout();    unsafe {  // Allocate enough space for the entire task. @@ -120,6 +161,7 @@  destroy: Self::destroy,  run: Self::run,  clone_waker: Self::clone_waker, + layout_info: &Self::TASK_LAYOUT,  },  });   @@ -149,32 +191,12 @@  }  }   - /// Returns the memory layout for a task. + /// Returns the layout of the task.  #[inline]  fn task_layout() -> TaskLayout { - // Compute the layouts for `Header`, `S`, `F`, and `T`. - let layout_header = Layout::new::<Header>(); - let layout_s = Layout::new::<S>(); - let layout_f = Layout::new::<F>(); - let layout_r = Layout::new::<T>(); - - // Compute the layout for `union { F, T }`. - let size_union = layout_f.size().max(layout_r.size()); - let align_union = layout_f.align().max(layout_r.align()); - let layout_union = unsafe { Layout::from_size_align_unchecked(size_union, align_union) }; - - // Compute the layout for `Header` followed `S` and `union { F, T }`. - let layout = layout_header; - let (layout, offset_s) = extend(layout, layout_s); - let (layout, offset_union) = extend(layout, layout_union); - let offset_f = offset_union; - let offset_r = offset_union; - - TaskLayout { - layout, - offset_s, - offset_f, - offset_r, + match Self::TASK_LAYOUT { + Some(tl) => tl, + None => abort(),  }  }   
diff --git a/src/task.rs b/src/task.rs index 7d1c433..8ecd746 100644 --- a/src/task.rs +++ b/src/task.rs 
@@ -99,6 +99,7 @@  /// # Examples  ///  /// ``` + /// # if cfg!(miri) { return; } // Miri does not support epoll  /// use smol::{future, Executor, Timer};  /// use std::thread;  /// use std::time::Duration; @@ -485,6 +486,7 @@  /// # Examples  ///  /// ``` + /// # if cfg!(miri) { return; } // Miri does not support epoll  /// use smol::{future, Executor, Timer};  /// use std::thread;  /// use std::time::Duration; 
diff --git a/src/utils.rs b/src/utils.rs index cb9b65e..189e9af 100644 --- a/src/utils.rs +++ b/src/utils.rs 
@@ -1,4 +1,4 @@ -use core::alloc::Layout; +use core::alloc::Layout as StdLayout;  use core::mem;    /// Aborts the process. @@ -36,29 +36,92 @@  t  }   -/// Returns the layout for `a` followed by `b` and the offset of `b`. -/// -/// This function was adapted from the currently unstable `Layout::extend()`: -/// https://doc.rust-lang.org/nightly/std/alloc/struct.Layout.html#method.extend -#[inline] -pub(crate) fn extend(a: Layout, b: Layout) -> (Layout, usize) { - let new_align = a.align().max(b.align()); - let pad = padding_needed_for(a, b.align()); - - let offset = a.size().checked_add(pad).unwrap(); - let new_size = offset.checked_add(b.size()).unwrap(); - - let layout = Layout::from_size_align(new_size, new_align).unwrap(); - (layout, offset) +/// A version of `alloc::alloc::Layout` that can be used in the const +/// position. +#[derive(Clone, Copy, Debug)] +pub(crate) struct Layout { + size: usize, + align: usize,  }   -/// Returns the padding after `layout` that aligns the following address to `align`. -/// -/// This function was adapted from the currently unstable `Layout::padding_needed_for()`: -/// https://doc.rust-lang.org/nightly/std/alloc/struct.Layout.html#method.padding_needed_for +impl Layout { + /// Creates a new `Layout` with the given size and alignment. + #[inline] + pub(crate) const fn from_size_align(size: usize, align: usize) -> Self { + Self { size, align } + } + + /// Creates a new `Layout` for the given sized type. + #[inline] + pub(crate) const fn new<T>() -> Self { + Self::from_size_align(mem::size_of::<T>(), mem::align_of::<T>()) + } + + /// Convert this into the standard library's layout type. + /// + /// # Safety + /// + /// - `align` must be non-zero and a power of two. + /// - When rounded up to the nearest multiple of `align`, the size + /// must not overflow. + #[inline] + pub(crate) const unsafe fn into_std(self) -> StdLayout { + StdLayout::from_size_align_unchecked(self.size, self.align) + } + + /// Get the alignment of this layout. + #[inline] + pub(crate) const fn align(&self) -> usize { + self.align + } + + /// Get the size of this layout. + #[inline] + pub(crate) const fn size(&self) -> usize { + self.size + } + + /// Returns the layout for `a` followed by `b` and the offset of `b`. + /// + /// This function was adapted from the currently unstable `Layout::extend()`: + /// https://doc.rust-lang.org/nightly/std/alloc/struct.Layout.html#method.extend + #[inline] + pub(crate) const fn extend(self, other: Layout) -> Option<(Layout, usize)> { + let new_align = max(self.align(), other.align()); + let pad = self.padding_needed_for(other.align()); + + let offset = leap!(self.size().checked_add(pad)); + let new_size = leap!(offset.checked_add(other.size())); + + // return None if any of the following are true: + // - align is 0 (implied false by is_power_of_two()) + // - align is not a power of 2 + // - size rounded up to align overflows + if !new_align.is_power_of_two() || new_size > core::usize::MAX - (new_align - 1) { + return None; + } + + let layout = Layout::from_size_align(new_size, new_align); + Some((layout, offset)) + } + + /// Returns the padding after `layout` that aligns the following address to `align`. + /// + /// This function was adapted from the currently unstable `Layout::padding_needed_for()`: + /// https://doc.rust-lang.org/nightly/std/alloc/struct.Layout.html#method.padding_needed_for + #[inline] + pub(crate) const fn padding_needed_for(self, align: usize) -> usize { + let len = self.size(); + let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1); + len_rounded_up.wrapping_sub(len) + } +} +  #[inline] -pub(crate) fn padding_needed_for(layout: Layout, align: usize) -> usize { - let len = layout.size(); - let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1); - len_rounded_up.wrapping_sub(len) +pub(crate) const fn max(left: usize, right: usize) -> usize { + if left > right { + left + } else { + right + }  }